package com.googlecode.mapperdao

import jdbc.Setup
import org.scalatest.{Matchers, FunSuite}
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import com.googlecode.mapperdao.schema.Schema

/**
 * @author kkougios
 */
@RunWith(classOf[JUnitRunner])
class SchemaSuite extends FunSuite with Matchers
{
	val (jdbc, mapperDao, queryDao) = Setup.setupMapperDao(List(ProductEntity, AttributeEntity))

	if (Setup.database == "postgresql") {
		test("schema CRUD") {
			createTables()

			val i1 = mapperDao.insert(ProductEntity, Product("test1", Set(Attribute("a1", "v1"), Attribute("a2", "v2"))))
			mapperDao.select(ProductEntity, i1.id).get should be(i1)

			val u1 = mapperDao.update(ProductEntity, i1, i1.copy(name = "x", attributes = i1.attributes + Attribute("a3", "v3")))
			mapperDao.select(ProductEntity, i1.id).get should be(u1)

			mapperDao.delete(ProductEntity, u1)
			mapperDao.select(ProductEntity, u1.id) should be(None)
		}

		test("schema query") {
			createTables()

			val i1 = mapperDao.insert(ProductEntity, Product("test1", Set(Attribute("a1", "v1"), Attribute("a2", "v2"))))

			import Query._

			(select from ProductEntity join(ProductEntity, ProductEntity.attributes, AttributeEntity) where AttributeEntity.name === "a1").toSet(queryDao) should be(Set(i1))
		}

		def createTables() {
			try {
				jdbc.update("drop schema test cascade")
			} catch {
				case _: Throwable =>
				// ignore as schema might not exist
			}
			Setup.queries(this, jdbc).update("ddl")
		}
	}

	case class Product(name: String, attributes: Set[Attribute])

	case class Attribute(name: String, value: String)

	object ProductEntity extends Entity[Int, SurrogateIntId, Product]
	{
		override val databaseSchema = Some(Schema("test"))

		val id = key("id") autogenerated (_.id)
		val name = column("name") to (_.name)
		val attributes = manytomany(AttributeEntity) to (_.attributes)

		def constructor(implicit m: ValuesMap) = new Product(name, attributes) with Stored
		{
			val id: Int = ProductEntity.id
		}
	}

	object AttributeEntity extends Entity[Int, SurrogateIntId, Attribute]
	{
		override val databaseSchema = Some(Schema("test"))

		val id = key("id") autogenerated (_.id)
		val name = column("name") to (_.name)
		val value = column("value") to (_.value)

		def constructor(implicit m: ValuesMap) = new Attribute(name, value) with Stored
		{
			val id: Int = AttributeEntity.id
		}
	}

}
